package es.buffygilmore.collectionapp;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
import es.buffygilmore.collectionapp.vo.Coleccion;
import es.buffygilmore.collectionapp.vo.Elemento;

/**
 * Acceso a la base de datos. Operaciones CRUD. Devuelve cursores en lugar de colecciones.
 */
public class CollectionAppDbAdapter {

	public static final String KEY_COLECCION_TITULO = "titulo";
	public static final String KEY_COLECCION_DESCRIPCION = "descripcion";
	public static final String KEY_COLECCION_ROWID = "_id";

	public static final String KEY_ELEMENTO_NOMBRE = "nombre";
	public static final String KEY_ELEMENTO_COMENTARIO = "comentario";
	public static final String KEY_ELEMENTO_PROPIEDAD = "propiedad";
	public static final String KEY_ELEMENTO_RUTA_IMAGEN = "rutaImagen";
	public static final String KEY_ELEMENTO_COLECCION = "idColeccion";
	public static final String KEY_ELEMENTO_ROWID = "_id";

	private static final String TAG = "CollectionAppDbAdapter";
	private DatabaseHelper mDbHelper;
	private SQLiteDatabase mDb;

	/**
	 * Database creation sql statement
	 */
	private static final String DATABASE_CREATE = "create table coleccion (_id integer primary key autoincrement, "
			+ "titulo text not null, descripcion text null);";
	private static final String DATABASE_CREATE_ELEMENTO_TABLE = "create table elemento (_id integer primary key autoincrement, "
			+ "nombre text not null, comentario text null, propiedad integer null, rutaImagen text null, idColeccion integer not null);";

	private static final String DATABASE_NAME = "colecciones";
	private static final String DATABASE_TABLE_COLECCION = "coleccion";
	private static final String DATABASE_TABLE_ELEMENTO = "elemento";
	private static final int DATABASE_VERSION = 7;

	private final Context mCtx;

	private static class DatabaseHelper extends SQLiteOpenHelper {

		DatabaseHelper(final Context context) {
			super(context, DATABASE_NAME, null, DATABASE_VERSION);
		}

		@Override
		public void onCreate(final SQLiteDatabase db) {

			db.execSQL(DATABASE_CREATE);
			db.execSQL(DATABASE_CREATE_ELEMENTO_TABLE);
		}

		@Override
		public void onUpgrade(final SQLiteDatabase db, final int oldVersion, final int newVersion) {
			Log.w(TAG, "Upgrading database from version " + oldVersion + " to " + newVersion
					+ ", which will destroy all old data");
			db.execSQL("DROP TABLE IF EXISTS coleccion");
			db.execSQL("DROP TABLE IF EXISTS elemento");
			this.onCreate(db);
		}
	}

	/**
	 * Constructor - takes the context to allow the database to be opened/created
	 * @param ctx the Context within which to work
	 */
	public CollectionAppDbAdapter(final Context ctx) {
		this.mCtx = ctx;
	}

	/**
	 * Open the notes database. If it cannot be opened, try to create a new instance of the
	 * database. If it cannot be created, throw an exception to signal the failure
	 * @return this (self reference, allowing this to be chained in an initialization call)
	 * @throws SQLException if the database could be neither opened or created
	 */
	public CollectionAppDbAdapter open() throws SQLException {
		this.mDbHelper = new DatabaseHelper(this.mCtx);
		this.mDb = this.mDbHelper.getWritableDatabase();
		return this;
	}

	public void close() {
		this.mDbHelper.close();
	}

	/**
	 * Create a new collection using the title and description provided. If the note is successfully
	 * created return the new rowId for that note, otherwise return a -1 to indicate failure.
	 *
	 * @param title the title of the note
	 * @param description the body of the note
	 * @return rowId or -1 if failed
	 */
	public long crearColeccion(final Coleccion coleccion) {
		final ContentValues initialValues = new ContentValues();
		initialValues.put(KEY_COLECCION_TITULO, coleccion.getTitulo());
		initialValues.put(KEY_COLECCION_DESCRIPCION, coleccion.getDescripcion());

		return this.mDb.insert(DATABASE_TABLE_COLECCION, null, initialValues);
	}

	/**
	 * Delete the note with the given rowId
	 * @param rowId id of note to delete
	 * @return true if deleted, false otherwise
	 */
	public boolean eliminarColeccion(final long rowId) {

		return this.mDb.delete(DATABASE_TABLE_COLECCION, KEY_COLECCION_ROWID + "=" + rowId, null) > 0;
	}

	/**
	 * Return a Cursor over the list of all notes in the database
	 *
	 * @return Cursor over all notes
	 */
	public Cursor obtenerTodasColecciones() {

		return this.mDb.query(DATABASE_TABLE_COLECCION, new String[] { KEY_COLECCION_ROWID,
				KEY_COLECCION_TITULO, KEY_COLECCION_DESCRIPCION }, null, null, null, null, null);
	}

	/**
	 * Return a Cursor positioned at the note that matches the given rowId
	 *
	 * @param rowId id of note to retrieve
	 * @return Cursor positioned to matching note, if found
	 * @throws SQLException if note could not be found/retrieved
	 */
	public Cursor obtenerColeccion(final long rowId) throws SQLException {

		final Cursor mCursor =

		this.mDb.query(true, DATABASE_TABLE_COLECCION, new String[] { KEY_COLECCION_ROWID,
				KEY_COLECCION_TITULO, KEY_COLECCION_DESCRIPCION }, KEY_COLECCION_ROWID + "="
				+ rowId, null, null, null, null, null);
		if (mCursor != null) {
			mCursor.moveToFirst();
		}
		return mCursor;

	}

	/**
	 * Update the note using the details provided. The note to be updated is specified using the
	 * rowId, and it is altered to use the title and body values passed in
	 *
	 * @param rowId id of note to update
	 * @param title value to set note title to
	 * @param descripcion value to set note body to
	 * @return true if the note was successfully updated, false otherwise
	 */
	public boolean modificarColeccion(final long rowId, final Coleccion coleccion) {
		final ContentValues args = new ContentValues();
		args.put(KEY_COLECCION_TITULO, coleccion.getTitulo());
		args.put(KEY_COLECCION_DESCRIPCION, coleccion.getDescripcion());

		return this.mDb.update(DATABASE_TABLE_COLECCION, args, KEY_COLECCION_ROWID + "=" + rowId,
				null) > 0;
	}

	public long crearElemento(final Elemento elemento) {
		final ContentValues initialValues = new ContentValues();
		initialValues.put(KEY_ELEMENTO_NOMBRE, elemento.getNombre());
		initialValues.put(KEY_ELEMENTO_COMENTARIO, elemento.getComentario());
		initialValues.put(KEY_ELEMENTO_PROPIEDAD, elemento.getPropiedad());
		initialValues.put(KEY_ELEMENTO_RUTA_IMAGEN, elemento.getRutaImagen());
		initialValues.put(KEY_ELEMENTO_COLECCION, elemento.getIdColeccion());

		return this.mDb.insert(DATABASE_TABLE_ELEMENTO, null, initialValues);
	}

	public boolean eliminarElemento(final long rowId) {

		return this.mDb.delete(DATABASE_TABLE_ELEMENTO, KEY_ELEMENTO_ROWID + "=" + rowId, null) > 0;
	}

	public Cursor obtenerElementosPorColeccion(final long idColeccion) {

		return this.mDb.query(DATABASE_TABLE_ELEMENTO, new String[] { KEY_ELEMENTO_ROWID,
				KEY_ELEMENTO_NOMBRE, KEY_ELEMENTO_COMENTARIO, KEY_ELEMENTO_PROPIEDAD,
				KEY_ELEMENTO_RUTA_IMAGEN, KEY_ELEMENTO_COLECCION }, KEY_ELEMENTO_COLECCION + "="
				+ idColeccion, null, KEY_ELEMENTO_NOMBRE + " COLLATE NOCASE", null, null);
	}

	public Cursor obtenerElemento(final long rowId) throws SQLException {

		final Cursor mCursor =

		this.mDb.query(true, DATABASE_TABLE_ELEMENTO, new String[] { KEY_ELEMENTO_ROWID,
				KEY_ELEMENTO_NOMBRE, KEY_ELEMENTO_COMENTARIO, KEY_ELEMENTO_PROPIEDAD,
						KEY_ELEMENTO_RUTA_IMAGEN, KEY_ELEMENTO_COLECCION }, KEY_ELEMENTO_ROWID + "="
								+ rowId, null, null, null, null, null);
		if (mCursor != null) {
			mCursor.moveToFirst();
		}
		return mCursor;

	}

	public boolean modificarElemento(final long rowId, final Elemento elemento) {
		final ContentValues args = new ContentValues();
		args.put(KEY_ELEMENTO_NOMBRE, elemento.getNombre());
		args.put(KEY_ELEMENTO_COMENTARIO, elemento.getComentario());
		args.put(KEY_ELEMENTO_PROPIEDAD, elemento.getPropiedad());
		args.put(KEY_ELEMENTO_RUTA_IMAGEN, elemento.getRutaImagen());
		args.put(KEY_ELEMENTO_COLECCION, elemento.getIdColeccion());

		return this.mDb.update(DATABASE_TABLE_ELEMENTO, args, KEY_ELEMENTO_ROWID + "=" + rowId,
				null) > 0;
	}

	public int obtenerNumeroElementosPorColeccion(final long idColeccion) {
		// final String total = "COUNT(*)";
		//
		// final Cursor cursor = this.mDb.query(DATABASE_TABLE_ELEMENTO, new String[] { total },
		// null,
		// null, null, null, null);

		final Cursor cursor = this.mDb.query(DATABASE_TABLE_ELEMENTO, new String[] {
				KEY_ELEMENTO_ROWID, KEY_ELEMENTO_NOMBRE, KEY_ELEMENTO_COLECCION },
				KEY_ELEMENTO_COLECCION + "=" + idColeccion, null, null, null, null);
		return cursor.getCount();

	}
}
